Bitset nature of Erlang guards What would you say if you'd see following code: -define(IS_ALPHA(C), (C =:= $a) or (C =:= $b) or (C =:= $c) or (C =:= $d) or (C =:= $e) or (C =:= $f) or (C =:= $g) or (C =:= $h) or (C =:= $i) or (C =:= $j) or (C =:= $k) or (C =:= $l) or (C =:= $m) or (C =:= $n) or (C =:= $o) or (C =:= $p) or (C =:= $q) or (C =:= $r) or (C =:= $s) or (C =:= $t) or (C =:= $u) or (C =:= $v) or (C =:= $w) or (C =:= $x) or (C =:= $y) or (C =:= $z) or (C =:= $A) or (C =:= $B) or (C =:= $C) or (C =:= $D) or (C =:= $E) or (C =:= $F) or (C =:= $G) or (C =:= $H) or (C =:= $I) or (C =:= $J) or (C =:= $K) or (C =:= $L) or (C =:= $M) or (C =:= $N) or (C =:= $O) or (C =:= $P) or (C =:= $Q) or (C =:= $R) or (C =:= $S) or (C =:= $T) or (C =:= $U) or (C =:= $V) or (C =:= $W) or (C =:= $X) or (C =:= $Y) or (C =:= $Z) ). The first thought comes in the mind is to replace this macro with one-liner: (X > $a andalso X < $z) orelse (X > $A andalso X < $Z) And really when you put this macro in the body is_alpha_cow(X) -> ?IS_ALPHA(X). is_alpha_bull(X) -> (X >= $a andalso X =< $z) orelse (X >= $A andalso X =< $Z). you receive predicted numbers: 1> sample:mbull(). {119,<<>>} 2> sample::mcow(). {1598,<<>>} Having measuring functions as follows: mcow() -> Bin = crypto:rand_bytes(1000), timer:tc(sample,measure_cow,[Bin]). mbull() -> Bin = crypto:rand_bytes(1000), timer:tc(sample,measure_bull,[Bin]). measure_cow(<<>>) -> <<>>; measure_cow(<>) -> is_alpha_cow(B), measure_cow(Bin). measure_bull(<<>>) -> <<>>; measure_bull(<>) -> is_alpha_bull(B), measure_bull(Bin). However when you put macro inside the guards: is_alpha_cow(X) when ?IS_ALPHA(X) -> true; is_alpha_cow(X) -> false. is_alpha_bull(X) when (X >= $a andalso X =< $z) orelse (X >= $A andalso X =< $Z) -> true; is_alpha_bull(X) -> false. you receive not only better result than in body, but also the best result of [{guard,body}x{cow,bull}] measurement: 3> sample:mbull(). {104,<<>>} 4> sample:mcow(). {64,<<>>}